package cn.source.system.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import cn.source.system.domain.RecoveryTable;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import cn.source.system.mapper.DbRecoveryMapper;
import cn.source.system.domain.DbRecovery;
import cn.source.system.service.IDbRecoveryService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;

/**
 * 数据库恢复记录Service业务层处理
 *
 * @author sourcebyte.vip
 * @date 2025-02-26
 */
@Service
public class DbRecoveryServiceImpl implements IDbRecoveryService {
    @Autowired
    private DbRecoveryMapper dbRecoveryMapper;

    /**
     * 查询数据库恢复记录
     *
     * @param id 数据库恢复记录主键
     * @return 数据库恢复记录
     */
    @Override
    public DbRecovery selectDbRecoveryById(Long id) {
        return dbRecoveryMapper.selectDbRecoveryById(id);
    }

    /**
     * 查询数据库恢复记录列表
     *
     * @param dbRecovery 数据库恢复记录
     * @return 数据库恢复记录
     */
    @Override
    public List<DbRecovery> selectDbRecoveryList(DbRecovery dbRecovery) {
        return dbRecoveryMapper.selectDbRecoveryList(dbRecovery);
    }

    /**
     * 新增数据库恢复记录
     *
     * @param dbRecovery 数据库恢复记录
     * @return 结果
     */
    @Override
    public int insertDbRecovery(DbRecovery dbRecovery) {
        return dbRecoveryMapper.insertDbRecovery(dbRecovery);
    }

    /**
     * 修改数据库恢复记录
     *
     * @param dbRecovery 数据库恢复记录
     * @return 结果
     */
    @Override
    //新开一个事务
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public int updateDbRecovery(DbRecovery dbRecovery) {
        return dbRecoveryMapper.updateDbRecovery(dbRecovery);
    }

    /**
     * 批量删除数据库恢复记录
     *
     * @param ids 需要删除的数据库恢复记录主键
     * @return 结果
     */
    @Override
    public int deleteDbRecoveryByIds(Long[] ids) {
        return dbRecoveryMapper.deleteDbRecoveryByIds(ids);
    }

    /**
     * 删除数据库恢复记录信息
     *
     * @param id 数据库恢复记录主键
     * @return 结果
     */
    @Override
    public int deleteDbRecoveryById(Long id) {
        return dbRecoveryMapper.deleteDbRecoveryById(id);
    }

    @Override
    public void downloadLog(Integer recoveryId, HttpServletResponse response) {
        String logs = dbRecoveryMapper.selectLog(recoveryId);
        //将logs写入response
        response.setContentType("application/octet-stream");
        response.setHeader("Content-Disposition", "attachment;filename=log.txt");
        //设置编码
        response.setCharacterEncoding("UTF-8");
        try (PrintWriter writer = response.getWriter()) {
            writer.write(logs);
            writer.flush();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void downloadBackupFile(List<RecoveryTable> recoveryTables, HttpServletResponse response) {
        // 将recoveryTables中的绝对路径的文件写入压缩文件中
        //将压缩文件写入response
        response.setContentType("application/zip");
        response.setHeader("Content-Disposition", "attachment; filename=backup.zip");
        //设置编码
        response.setCharacterEncoding("UTF-8");

        //判断文件是否存在
        String filePath1 = recoveryTables.get(0).getFileAbsolutePath();
        File file = new File(filePath1);
        File parentFile = file.getParentFile();
        if (!parentFile.exists()) {
            String log = "文件已经被删除，无法恢复";
            throw new RuntimeException(log);
        }
        //创建一个压缩文件
        try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) {
            for (RecoveryTable table : recoveryTables) {
                String filePath = table.getFileAbsolutePath();
                File fileToZip = new File(filePath);
                if (fileToZip.exists()) {
                    FileInputStream fis = new FileInputStream(fileToZip);
                    ZipEntry zipEntry = new ZipEntry(fileToZip.getName());
                    zipOut.putNextEntry(zipEntry);
                    byte[] bytes = new byte[1024];
                    int length;
                    while ((length = fis.read(bytes)) >= 0) {
                        zipOut.write(bytes, 0, length);
                    }
                    fis.close();
                }
            }
            // 刷新输出流确保数据全部输出
            zipOut.flush();
        } catch (IOException e) {
            // 出现异常可以给客户端返回错误信息
            e.printStackTrace();
        }
    }
}
